﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using System.Xml;
using NHibernate;
using VitCode.BaseDataPageCreator.Setting;
using VitCode.Castle.DataAccess;


namespace VitCode.BaseDataPageCreator
{
	/// <summary>
	/// PageRuleHelper 的摘要說明。
	/// </summary>
	public class PageRuleHelper
	{
		public string m_DbRule = "db_rule", m_Only = "唯一性", m_Exists = "存在性", m_IsInt="整數";
		private ObjXmlReader m_XmlReader;
		private PageLoadHelper m_LoadHelper;

		private ISession m_AccSession;

		public ISession AccSession
		{
			get
			{
				if (m_AccSession == null)
					m_AccSession = new BaseDataAccess().Session;
				return m_AccSession;
			}
			set { m_AccSession = value; }
		}

		private bool m_IsUpdate;

		public bool IsUpdate
		{
			get { return m_IsUpdate; }
			set { m_IsUpdate = value; }
		}

		public PageRuleHelper(string settingXmlPath)
		{
            m_LoadHelper = new PageLoadHelper(settingXmlPath);
			m_XmlReader = m_LoadHelper.XmlReader;
		}

		public XmlNodeList GetProDBRuleXmlNodes(XmlNode proNode)
		{
			return m_XmlReader.GetChildNodesFromXML(proNode, m_DbRule, true);
		}

		public XmlNode GetClassNode(XmlNode roleNode)
		{
			string className = m_XmlReader.GetNodeAttributeValue(roleNode, m_LoadHelper.CLASS_NAME, true);

			if (className.Length > 0)
			{
				return m_XmlReader.GetClassXMLNode(className);
			}
			else
			{
				string strNameSpace = "";
				XmlNode tempNode = roleNode;
				while (strNameSpace.Length == 0 && tempNode != null)
				{
					tempNode = tempNode.ParentNode;
					strNameSpace = m_XmlReader.GetNodeAttributeValue(tempNode, m_LoadHelper.NAME_SPACE, true);
				}
				return tempNode;
			}
		}

        public string GetProAttrValue(XmlNode roleNode,string attrName)
        {
            string proName = "";
            XmlNode proNode = roleNode.ParentNode;
            if (proNode.Name == m_LoadHelper.PROPERTY)
                proName = m_XmlReader.GetNodeAttributeValue(proNode, attrName, true);
            return proName;
        }


		public bool CheckRule(string ruleTypeName, string proName, string proMemo, object obj, out string msg, string timingIsUseProName)
		{
			msg = "";
			string className = obj.GetType().Name;
			string classKeyProName = m_LoadHelper.GetClassKeyPropertyName(className);
			string objMemo = m_XmlReader.GetNodeAttributeValue(className, m_LoadHelper.MEMO);
			string strKeyProVal = m_LoadHelper.GetObjProStringValue(obj.GetType().GetProperty(classKeyProName), obj);
			string strProVal = m_LoadHelper.GetObjProStringValue(obj.GetType().GetProperty(proName), obj);
			if (ruleTypeName == null || ruleTypeName.Length == 0 || ruleTypeName == m_Only)
			{
			    string hql = "From " + className + " o where o." + proName + "='" + strProVal + "' and o." + classKeyProName +
			                 "<>'" +
			                 strKeyProVal + "'";
                if (!string.IsNullOrEmpty(timingIsUseProName))
                {
                    hql += " and " + timingIsUseProName + "=1 ";
                    //var keyPro = obj.GetType().GetProperty(classKeyProName);
                    //if(keyPro!=null && keyPro.PropertyType == typeof(Guid))
                    //{
                    //    var proVal = keyPro.GetValue(obj, null);
                    //    if (proVal != null)
                    //        hql += " and "+classKeyProName+"<>'"+Guid.Empty+"'";
                    //}
                }
                IList list = AccSession.CreateQuery(hql).List();
				if (list != null && list.Count > 0)
					msg = "\"" + proMemo + "\"為\"" + strProVal + "\"的\"" + objMemo + "\"已經存在,不能重複";
			}
			else if (ruleTypeName == m_Exists)
			{
			}

			return msg.Length == 0;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ruleNode"></param>
		/// <returns></returns>
		public bool CheckPropertySaveDBRule(object obj, XmlNode ruleNode, out string msg,string timingIsUseProName)
		{
			XmlNode classNode = GetClassNode(ruleNode);
            string proName = GetProAttrValue(ruleNode, m_LoadHelper.NAME);
            string proMemo = GetProAttrValue(ruleNode, m_LoadHelper.MEMO);

			if (classNode == null)
			{
				msg = "找不到要驗證的物件類型";
				return false;
			}
			if (proName.Length == 0)
			{
				msg = "找不到要驗證的屬性";
				return false;
			}
			Type classType = m_LoadHelper.GetClassTypeByClassNodeName(classNode.Name);
			if (!classType.Equals(obj.GetType()))
			{
				msg = "指定的物件類型與驗證物件的類型不一致";
				return false;
			}
			string ruleTypeName = m_XmlReader.GetNodeAttributeValue(ruleNode, m_LoadHelper.TYPE_NAME, true);
			CheckRule(ruleTypeName, proName,proMemo, obj, out msg,timingIsUseProName);
			return msg.Length == 0;
		}

		public bool CheckPropertySaveDBRules(object obj, XmlNode proNode, out StringCollection scMsg, string timingIsUseProName)
		{
			scMsg = new StringCollection();
			int errorAmount = 0;
			XmlNodeList ls = m_XmlReader.GetChildNodesFromXML(proNode, m_DbRule, true);
			for (int i = 0; ls != null && i < ls.Count; i++)
			{
				string strMsg;
				CheckPropertySaveDBRule(obj, ls[i], out strMsg,timingIsUseProName);
				if (strMsg.Length > 0)
				{
					scMsg.Add(strMsg);
					errorAmount++;
				}
			}
			return errorAmount == 0;
		}

		public bool CheckObjectSaveDBRules(object obj, out StringCollection scObjMsg)
		{
			scObjMsg = new StringCollection();
		    string strTypeName = "";
            PropertyInfo pi = obj.GetType().GetProperty(m_LoadHelper.TYPE_NAME);
            if(pi!=null)
            {
                object objTypeName = pi.GetValue(obj, null);
                if (objTypeName != null)
                    strTypeName = objTypeName.ToString();
            }
		    XmlNode tempNode = m_XmlReader.GetClassTypeNameXMLNode(obj.GetType().Name, strTypeName);
            if(tempNode == null)
                tempNode = m_XmlReader.GetClassXMLNode(obj.GetType().Name);
		    var timingIsUseProName = m_XmlReader.GetNodeAttributeValue(tempNode, m_LoadHelper.TIMING_IS_USE_PRO_NAME,true);
			XmlNodeList proNodes = m_XmlReader.GetChildNodesFromXML(tempNode, m_LoadHelper.PROPERTY);
			for (int i = 0; proNodes != null && i < proNodes.Count; i++)
			{
				StringCollection scProMsg;
				CheckPropertySaveDBRules(obj, proNodes[i], out scProMsg,timingIsUseProName);
				if (scProMsg.Count > 0)
				{
					foreach (string proMsg in scProMsg)
						scObjMsg.Add(proMsg);
				}
			}
			return scObjMsg.Count == 0;
		}

		private ObjXmlReader m_RuleXmlReader = new ObjXmlReader(AppDomain.CurrentDomain.BaseDirectory+"Setting/PageRuleTypeSetting.xml");

		private void SetRuleCtlInfoString(ref StringBuilder sbCtlInfoString,string proName,XmlNode settingNode)
		{
			string proVal = m_RuleXmlReader.GetNodeAttributeValue(settingNode, proName, true);
			if(sbCtlInfoString.Length > 0)
				sbCtlInfoString.Append(",");
			sbCtlInfoString.Append( proName + ":" + proVal);
		}

		const string TYPE_NAME="TypeName",ERR_MSG="ErrMsg",REG_EXP_VALUE="RegExpValue";
		
		public string GetPageRuleCtlInfoByTypeName(string typeName)
		{
			StringBuilder sbReVal = new StringBuilder();
			if(typeName == null || typeName.Length == 0)
				return "";

			sbReVal.Append(TYPE_NAME + ":" + typeName);
			
			XmlNode nd = m_RuleXmlReader.GetXmlNode("setting/"+typeName);
			if(nd == null)
				return sbReVal.ToString();

			
			SetRuleCtlInfoString(ref sbReVal, ERR_MSG, nd);
			SetRuleCtlInfoString(ref sbReVal, REG_EXP_VALUE, nd);

			return sbReVal.ToString();
			
		}

        public string GetPageRuleRegByTypeName(string typeName)
        {
            string val = "";
            StringBuilder sbReVal = new StringBuilder();
            if (typeName == null || typeName.Length == 0)
                return val;

            XmlNode nd = m_RuleXmlReader.GetXmlNode("setting/" + typeName);
            if (nd == null)
                return val;


            val = m_RuleXmlReader.GetNodeAttributeValue(nd, REG_EXP_VALUE, true);

            return val;
        }

        public string GetPageRuleErrMsgByTypeName(string typeName)
        {
            string val = "";
            StringBuilder sbReVal = new StringBuilder();
            if (typeName == null || typeName.Length == 0)
                return val;

            XmlNode nd = m_RuleXmlReader.GetXmlNode("setting/" + typeName);
            if (nd == null)
                return val;


            val = m_RuleXmlReader.GetNodeAttributeValue(nd, ERR_MSG, true);

            return val;
        }
	}
}
